#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# -----------------------------------------------------------------------------
#   supplying c grammar functions
#
#

from debug import *

from cglobal import *


# 
def get_split_str(s):
    "将字符串按照空格分开"
    subs = s.rstrip().split()
    l = len(subs)
    if l>1:
        return subs[0], s[len(subs[0])+1:].rstrip()
    else:
        return '', s
    #try:
    #    i = s.index(' ')
    #except ValueError:
    #    return '', s

    #if i!= -1:
    #    return s[0:i], s[i+1:]
    #else:
    #    return '', s

# 
def get_format_str(s, prefix=4):
    "对字符串进行组合，以便进行打印"
    lines = s.split('\n')
    fstr = lines[0]
    fstr += '\n'
    try:
        for line in lines[1:]:
            fstr += ' '*prefix
            fstr += line
            fstr += '\n'
    except:
        pass
    # 将\n跳去
    return fstr.rstrip()

#
#    解释标识符
#       可能引起标识符删除
#
def parser_search_name(exp, cm_map):
    """
    @brief 解释标识符
    @param exp    为待检索的表达式
    @param cm_map 为表达式的位图
    """
    # 按照分支的方法存储
    name = 'NULL'
    ## 如果本函数存在待关注的表达式，且本行没有注释，使用表达式
    if (cm_map.has_key(exp[TK_START])):
        # 如果存在对应的注释
        name = cm_map[(exp[TK_START])]
        del cm_map[(exp[TK_START])]
    else:
        # 如果不存在对应的注释，采用表达式
        if (exp[TK_EXPR] != ''):
            name = exp[TK_EXPR] #.rstrip()
            #print name
        if name[-2] == ';':
            name = name[0:-2]
    return name

# 将相同节点的表达式合并
# 
def combine_node_exp(exp_list):
    new_list = ['NODE', exp_list[TK_START], exp_list[TK_END], []]
    # 预备作为新的列表的元素
    # 如果合并完之后，len(context)==1，则再次合并
    # start 取整体start
    context = ['DONENODE', exp_list[TK_START], 0, []]
    last_i = -1

    # 遍历一个节点的所有子节点（表达式）
    for i in range(len(exp_list[TK_EXPR])):
        exp = exp_list[TK_EXPR][i]
        # 如果待处理的表达式类型为DONENODE，则可以合并列表
        if (exp[TK_TYPE] == 'DONENODE'):
            if (i - last_i == 1):
                # 此时合并，并更新last_i
                context[TK_EXPR].extend(exp[TK_EXPR])
                context[TK_END] = exp[TK_END]
                last_i = i
            else: 
                # 说明上次已经不是DONENODE了，新建context
                context = ['DONENODE', exp[TK_START], 0, []]
                context[TK_EXPR].extend(exp[TK_EXPR])
                context[TK_END] = exp[TK_END]
                last_i = i
        else: 
            #如果不是这个类型，说明遇到了新的类型，
            # 将有效的已有类型压入
            if (len(context[TK_EXPR]) != 0):
                new_list[TK_EXPR].append(context)
            if (ENABLE_HANDLE_DEBUG==1): print'==GO0 ', new_list[TK_EXPR]
            new_list[TK_EXPR].append(exp)

            # 遇到不同的类型的时候，先将类型复位，
            # 这样可以避免后期误将已经压入的DONENODE再次压入，
            # 此处需要注意，如果直接对context[TK_EXPR]操作将会影响已经压入堆栈的部分
            # context[TK_EXPR] = []
            context = ['DONENODE', exp[TK_START], 0, []]
        if (ENABLE_HANDLE_DEBUG==1): print'==GO ', exp, '\n==Go2', context, '\n==Go3', new_list
        #print('==GOC ', context)

    # 如果最后一个表达式类型为DONENODE，应增加到list里面
    if (exp[TK_TYPE] == 'DONENODE'):
        new_list[TK_EXPR].append(context)

    if (ENABLE_HANDLE_DEBUG==1): print '==GOE ', new_list, '\n', context

    # 如果只有一个，直接采用新的节点
    if (len(new_list[TK_EXPR]) == 0):
        new_list = context
    elif len(new_list[TK_EXPR]) == 1:
        # 此处原先是 new_list = context，
        # 需要区分是否有效的数据
        #if (new_list[TK_EXPR][0][TK_EXPR] == 'DONENODE'
        #        or 1):
        new_list = new_list[TK_EXPR][0]
    return new_list

def get_if_str(fmt):
    s = fmt.rstrip()
    if (s[-1] != '?'):
        return s+'?'
    else:
        return s

I_START    =0
I_END    =1

from chandler import fbasic

import sys
#sys.path.insert(0,"..")

import clang.doxyyacc as doxyyacc
import clang.vlex as vlex


class cgrammar(fbasic):
    """
        class C grammar
    """
    def __init__(self, keyfile=""):
        """
            Construct
        """
        fbasic.__init__(self)
        self.doxyp, self.elist, self.lexer = doxyyacc.doxyyacc()
        self.slex = vlex.vlex({})
        if (keyfile!=""):
            self.slex.load_keyword_from_file(keyfile)

    # 搜索表达式范围内的注释
    #    
    #    exp        表达式    [TK_TYPE, TK_START, TK_END, TK_EXPR, TK_MID]
    #    cm_map    注释所在的map
    #    start     开始
    #    end       结束标志
    # 本函数会搜索start to end的范围内的注释
    #    
    #    返回 注释列表，如果是单节点，则在expr中，否则在
    #    [TYPE, START, END, expr]
    #    [TYPE, START, END, [ NODE, NODE ]]
    #    
    def parser_search_comment(self, exp, cm_map, start, end):
        cm_list=[]

        if (exp[TK_TYPE] == '{}'):
            if (ENABLE_HANDLE_DEBUG==1): print('parser search:', start, end+1)
            # 遍历本段文本
            # 此处要注意层次结构保持统一，插值的部分应作为一个NODE，方便进行独立计算
            # 遍历末尾时，要包含末尾行
            cm_list=['DONENODE', start, end, []]

            # 如果包含相关的注释，则将其插入到cm_list中
            for i in range(start+1, end+1):
                if cm_map.has_key(i):
                    cm_list[TK_EXPR].append(['DONENODE', i, i, cm_map[i]])
                    del cm_map[i]

            if (len(cm_list[TK_EXPR])==0):
                # 如果cm_list长度为0，需要将代码嵌入，此时需要注意，将end+1
                code = self.code_pop(start+1, end)
                if (ENABLE_HANDLE_DEBUG==1): print('parser code:', code)
                # 如果代码不为空，则将整段代码进行处理
                if (code != ""):
                    # 如果设置了文本绘图选项，按照;进行分隔
                    if self.flag_get('text'):
                        code_slide = code.split(';')
                        #print code_slide
                        for n in code_slide:
                            nn = n.strip()
                            #print nn
                            if nn:
                                #if (nn[0] == '"' and nn[-1] == '"'):   # 此处原先打算进行字符串的判断后，进行处理
                                #    nn = nn[1:-1]
                                cm_list[TK_EXPR].append(['DONENODE', start+1, start+1, nn])

                        if (len(code_slide) >= 2):
                            cm_list[TK_END] = end - 1
                        #print cm_list
                    else:
                        # 如果未设置，则按照传统的方法截取节点
                        cm_list[TK_EXPR].append(['DONENODE', start+1, start+1, code])

        elif (exp[TK_TYPE][0:4] == 'DONE'):
            # 如果已经是DONE，则直接返回，不做修改
            cm_list = exp[TK_EXPR]
        else:
            # 返回单节点
            cm_list = [exp[TK_TYPE], start, end, parser_search_name(exp, cm_map)]
        return cm_list

    def parse_single(self):
        return

    # 
    #     合并表达式
    #       exp  :
    #       ipos :   位置
    #       lstart
    #       lend:
    def precombine_exp(self, exp, ipos, lstart, lend):
        #
        #    考虑到解析的递归，认为每次解析的时候，元素均已经展开完毕
        #        
        #    典型 {
        #        1    sta;    
        #        2    sta2;        NODE
        #            ...
        #        n    sta3; 
        #        }
        #
        try:
            compact = 1
            while(compact):
                # 先判断是否满足连续的条件，
                #    按照先入后出的原则
                #    如果历史{}不被当前范围(lstart, lend)所包含
                #    则退出本循环，进行解析
                #        如果长度为1，说明没有包含
                #        如果长度>1，说明需要被包含
                exp.append(self.top())
                ipos.append(exp[-1][TK_START: TK_END+1])

                if (ENABLE_HANDLE_DEBUG==1): print('cbe', ipos, exp)    #

                # 如果压入的解出来的数据的范围不在当前{}之内，则结束这个循环
                if (ipos[-1][I_START] <= lstart or
                        ipos[-1][I_END] >= lend):
                    ipos.pop()
                    exp.pop()
                    raise IndexError
                # 只有真正满足需要，才将precombine_exp pop
                self.rpop()
        except IndexError:
            # 说明已经不存在多余的数量，或者文件已经解析完毕
            if (ENABLE_HANDLE_DEBUG==1): print ('com1', ipos, exp)
            return


    #
    #    解析组合表达式
    #        只有当前top为{}
    #        cm_map    为代码段对应的注释
    #        只有com的校验
    #    
    #    返回： 封装一层后的内容
    #        如果组合表达式中只包含
    #   
    #
    def parse_comp(self, cm_map):
        # 不考虑长度的问题，即认为堆栈中存在较多的数据
        exp = []    # 表达式
        ipos=[]     # 表达式的范围，压入的是[起始，终止]位置
        # 如果为{}，需要判断
        lstart, lend = self.top()[TK_START: TK_END+1]
        tlist = ['NODE', lstart, lend, []]    # 列表

        # 首先将当前范围和当前数据保存
        exp.append(self.rpop())
        ipos.append([lstart, lend])

        # 对表达式进行预合并
        self.precombine_exp(exp, ipos, lstart, lend)
        start=lstart
        end=lend

        if (len(exp) == 1):
            #如果长度为1，说明是一个标准长度
            # 此时只将 注释项 导入
            # 返回一个简单的注释
            tlist = self.parser_search_comment(exp[-1], cm_map, exp[-1][TK_START], exp[-1][TK_END])
            #print tlist
            self.rpush(tlist)
            # 此时需要退出
            return tlist

        # 此时exp是按照逆序的方式组织的，需要从尾部开始搜索
        while len(exp) > 1:
            # 如果当前元素的长度在{}以下，实际上这个事情在机制上能够保证
            #if (exp[-1][TK_START] > start):

            # 此时需要依次压入 不同段 的内容
            if (start <= exp[-1][TK_START]-1):
                # 如果两个表达式间还有注释，将其解析，并插入
                # 如果两部分行号连续，则不插入
                cm_res = self.parser_search_comment(['{}'], cm_map, start, exp[-1][TK_START]-1)
                # 如果注释结果为空，也不插入
                if (cm_res[TK_EXPR] != []):
                    tlist[TK_EXPR].append(cm_res)
                else:
                    # 如果注释结果不为空，此时判断起、止行号是否满足需要
                    # 需要完善TBD
                    pass
                if (ENABLE_HANDLE_DEBUG==1): print('!',cm_res)
            # 将堆栈中的list插入
            tlist[TK_EXPR].append(exp[-1])
            if (ENABLE_HANDLE_DEBUG==1):  print('loop', tlist[TK_EXPR])
            start = exp[-1][TK_END]+1
            exp.pop()
            # 此时将范围其实更新为新的问题

        # 当长度  为1的时候，将末尾的空间加上
        #    此时需明确长度不为1
        #if ENABLE_HANDLE_DEBUG==1: print 'comp last', start, lend
        # 只在start < lend时才进行后续的插入，否则认为有故障
        if (1 or start < lend):
            cm_res = self.parser_search_comment(exp[-1], cm_map, start, lend)
            if (cm_res[TK_EXPR] != []):
                tlist[TK_EXPR].append(cm_res)
            else:
                # 如果
                if (ENABLE_HANDLE_DEBUG==1): print 'comp last', start, lend
            #    tlist[TK_EXPR].append(['DONENODE', start, start, 'null'])

        # 将结果合并
        new_list = combine_node_exp(tlist)
        self.rpush(new_list)
        if ENABLE_HANDLE_DEBUG==1: print 'comp', new_list

        return new_list

    def get_switch(self, old):
        #print "GET_SW", old
        result = []
        last_case = None
        case_node = None
        end_l = 0
        cnt = 0

        for leaf in old[TK_EXPR]:
            #print '-'*5, leaf
            if (leaf[TK_TYPE] == 'DONECASE'
                or leaf[TK_TYPE] == 'DONEDEFAULT'):
                if (last_case):
                    # 如果不为空，需要将之前的压入
                    result.append(last_case)
                # 重新初始化
                last_case = leaf
                case_node = last_case[TK_EXPR][0]
                case_expr = last_case[TK_EXPR][1]
                cnt = 0

            elif (leaf[TK_TYPE] == 'DONEBREAK'):
                # 如果遇到break，说明上一次case结束
                last_case[TK_EXPR][1] = case_expr
                result.append(last_case)
                result.append(leaf)
                last_case = None
            else:
                # 如果是普通节点，将其加入到case/default的分支的默认语句中
                # 此时需要重构语句
                
                if cnt == 0:
                    # 第一次压入时，重新构造NODE节点，覆盖原先的语句
                    case_expr = ['NODE', leaf[TK_START], leaf[TK_END], [leaf]]
                else:
                    # 后续操作中，压入并更新end
                    case_expr[TK_EXPR].append(leaf)
                cnt += 1
                end_l = leaf[TK_END]
                case_node[TK_END] = case_expr[TK_END] = last_case[TK_END] = end_l

        if (leaf[TK_TYPE] != 'DONEBREAK'):
            result.append(last_case)

        #print '='*50
        #for leaf in result:
        #    print '-'*5, leaf

        return ['NODE', old[TK_START], old[TK_END], result]
        #return old

    #    从tklist堆栈中解析数据
    #    重新组织注释
    #        
    #    调用：    parser_search_comment
    #
    #    
    def parse(self):
        # 初始化
        exp = []    # 表达式
        tlist = []    # 列表
        token = self.top()[TK_TYPE]
        if (token=='{}'):
            # 解析{}
            self.parse_comp(self.comment_map)
        elif (token == 'SINGLE'):
            exp.append(self.rpop())
            start = exp[0][TK_START]
            end = exp[0][TK_END]
            text = parser_search_name(exp[0], self.comment_map)

            self.push(['DONENODE', start, end, [['DONENODE', start, end, text]]])
        elif (token == 'IFELSE'):
            # 存储相关数据, 查找相关数据
            exp.append(self.rpop())    # if
            exp.append(self.rpop())    # else     内容
            exp.append(self.rpop())    # if    内容

            # 更新起始位置和最终位置
            start = exp[0][TK_START]
            mid = exp[0][TK_MID]
            end = exp[1][TK_END]
            # 结束标志应以else结束内容为准
            exp[0][TK_END] = exp[1][TK_END]
            # 更新标识符
            exp[0][TK_EXPR] = parser_search_name(exp[0], self.comment_map)
            exp[0][TK_EXPR] = get_if_str(exp[0][TK_EXPR])

            # 压入相关的工作
            tlist.append(exp[0])    # 
            tlist.append(exp[2])    #
            tlist.append(exp[1])    #

            # 压入 还要压入 中间值
            self.push(['DONEIFELSE', start, end, tlist, mid])
            #print(self.comment_map)
            if ENABLE_HANDLE_DEBUG==1: print '==PARSER: IFELSE', start, end, exp[0], '\n', exp[1], '\n', exp[2]
        elif (token == 'IF'
                or token == 'WHILE'
                or token == 'DO'
                #or token == 'SWITCH'
                #or token == 'CASE'
                #or token == 'DEFAULT'
                ):
            # 此时对于单选择的东西来说处理都是类似的
            exp.append(self.rpop())    # 判断内容
            exp.append(self.rpop())    # 内容

            # 由于相关语句的下一句的偏移量未定
            exp[0][TK_END] = exp[1][TK_END]

            # 更新标记
            exp[0][TK_EXPR] = parser_search_name(exp[0], self.comment_map)
            if (token != 'DEFAULT'):
                exp[0][TK_EXPR] = get_if_str(exp[0][TK_EXPR])

            # 更新起始位置和最终位置
            start = exp[0][TK_START]
            end = exp[0][TK_END]

            # 压入相关的工作
            tlist.append(exp[0])    # 
            tlist.append(exp[1])    #

            # 压入相关数据
            self.push(['DONE'+token, start, end, tlist])
        elif (token == 'CASE'
              or token == 'DEFAULT'):
            # 此时对于单选择的东西来说处理都是类似的
            exp.append(self.rpop())    # 判断内容

            # 由于相关语句的下一句的偏移量未定
            exp[0][TK_END] = exp[0][TK_START] 

            # 更新标记
            exp[0][TK_EXPR] = parser_search_name(exp[0], self.comment_map)
            # 由于此时压入一个空的语句，注释被空语句覆盖
            #exp[0][TK_EXPR] = exp[1][TK_EXPR]
            #print self.comment_map, exp[0][TK_EXPR]
            if (token != 'DEFAULT'):
                exp[0][TK_EXPR] = get_if_str(exp[0][TK_EXPR])

            # 更新起始位置和最终位置
            start = exp[0][TK_START]
            end = exp[0][TK_END]

            # 压入相关的工作
            tlist.append(exp[0])    # 

            self.push(['SINGLE', start, end, 'NOP'])

            tlist.append(self.rpop())    #

            # 压入相关数据
            self.push(['DONE'+token, start, end, tlist])
            #print self.top()
        elif (token == 'SWITCH'):
            judge = self.rpop()
            states = self.rpop()

            #print 'SWITCH', judge, states
            newstates = self.get_switch(states)

            exp.append(judge)    # 判断内容
            exp.append(newstates)    # 内容

            # 由于相关语句的下一句的偏移量未定
            exp[0][TK_END] = exp[1][TK_END]

            # 更新标记
            exp[0][TK_EXPR] = parser_search_name(exp[0], self.comment_map)
            #if (token != 'DEFAULT'):
            #    exp[0][TK_EXPR] = get_if_str(exp[0][TK_EXPR])

            # 更新起始位置和最终位置
            start = exp[0][TK_START]
            end = exp[0][TK_END]

            # 压入相关的工作
            tlist.append(exp[0])    # 
            tlist.append(exp[1])    #

            # 压入相关数据
            self.push(['DONE'+token, start, end, tlist])
            #print "AFTER", self.top()

        elif (token == 'FOR'):
            # 在FOR循环中，需要注意针对注释进行进一步的分析，其余部分和IF均类似
            exp.append(self.rpop())    # 判断内容
            exp.append(self.rpop())    # 内容

            # 由于相关语句的下一句的偏移量未定
            exp[0][TK_END] = exp[1][TK_END]

            # 更新标记
            comment = parser_search_name(exp[0], self.comment_map)

            # 对FOR的语句单独解析注释, 使用;作为for语句注释的分隔符
            lines = comment.split(';')
            if (len(lines) > 1):
                lines.append('')
                lines.append('')
                # TK_EXPR 为FOR判断条件， TK_EXPR0 为初始化条件， TK_EXPR2为迭代语句
                if (lines[0].strip() != ''):
                    exp[0][TK_EXPR0] = lines[0]
                if (lines[1].strip() != ''):
                    exp[0][TK_EXPR] = lines[1]
                if (lines[2].strip() != ''):
                    exp[0][TK_EXPR2] = lines[2]
            else:
                exp[0][TK_EXPR] = comment

            # 在FOR循环后智能增加?
            exp[0][TK_EXPR] = get_if_str(exp[0][TK_EXPR])

            # 更新起始位置和最终位置
            start = exp[0][TK_START]
            end = exp[0][TK_END]

            # 压入相关的工作
            tlist.append(exp[0])    # 
            tlist.append(exp[1])    #

            # 压入相关数据
            self.push(['DONE'+token, start, end, tlist])
        elif (token == 'BREAK'
                or token == 'CONTINUE'
                or token == 'GOTO'
                or token == 'RETURN'
                ):
            exp.append(self.rpop())    # 判断内容
            tlist.append(exp[0])

            exp[0][TK_EXPR] = token[0:3]+' '+parser_search_name(exp[0], self.comment_map)

            # 更新起始位置和最终位置
            start = exp[0][TK_START]
            end = exp[0][TK_END]

            self.push(['DONE'+token, start, end, tlist])
        elif (token=='FUNC'):
            # 对函数而言，直接增加到内容中

            # 获取函数的标识符，注释等
            raw_expr = self.rpop()
            declaration = raw_expr[TK_EXPR]
            #print declaration
            if (ENABLE_HANDLE_DEBUG==1): self.trace()

            # 获取
            while (self.len() > 0):
                # 获取相关问题
                exp.append(self.rpop())
                # 函数文件
                tlist.append(self.parser_search_comment(exp[-1], self.comment_map, exp[-1][TK_START], exp[-1][TK_END]))

            # 考虑到*等操作符，采用(之前的那个标识符作为函数名
            namel = declaration.split()
            for i in range(1, len(namel)):
                if (namel[i] == '('):
                    i = i-1
                    break
            name = namel[i]
            if ENABLE_HANDLE_DEBUG==1: print('FUNC', name, exp)

            # 更新起始行
            start = raw_expr[TK_START]
            if (start != 0 and start < exp[0][TK_START]):
                exp[0][TK_START] = start

            # 打印函数
            self.printer(name, exp[0])
            return 
        #print self.top()

    def update_fun_data(self, dst_map, index, data_map, filter=-1):
        """
        @brief 更新函数内的数据
        """
        # -1表示不判断，>=0的数表示仅有匹配的值才会输出
        key_i = 0
        line_len = 0
        # 获取函数作用域内的函数列表，依次添加到index中
        for key in data_map.iterkeys():
            if (filter== -1) or (data_map[key] == filter):
                elem = FUN_STR_FMT%key
                line_len += len(elem)
                dst_map[index] += elem
                if line_len > FUN_STR_WIDTH:
                    dst_map[index] += '\n'
                    line_len = 0
                #dst_map[index] += ' '
                # 为便于显示，增加自动换行功能
                key_i += 1

    def get_param_map(self, data_map, filter=-1):
        r={}
        # 获取函数作用域内的函数列表，依次添加到index中
        for key in data_map.iterkeys():
            if (filter== -1) or (data_map[key] == filter):
                r[key] = ""
        return r

    def analyze_gvin_data(self, text):
        # 使用vlex将读入的全局变量进行分解拆分
        l = self.slex.lexer
        #print "analyze gin", text
        tokens = l.input(text)
        r = {}
        while 1:
            tok = l.token()
            if not tok: break
            #sys.stdout.write("(%s,%r,%d,%d)\n" % (tok.type, tok.value, tok.lineno,tok.lexpos))
            if (tok.type == 'ID'):
                r[tok.value] = VTYPE_GLOBAL
        return r

    def update_gvarin(self, out_map, fun_map):
        # 在被引用的token中剔除入参、局部变量、函数调用
        #print "gvar", self.gvarin_map
        #print "fcall", fun_map
        for key in fun_map:
            try:
                self.gvarin_map[key] = VTYPE_FUN
            finally:
                pass

        #print "out_map", out_map
        for key,v in out_map.items():
            if v != VTYPE_GLOBAL:
                try:
                    self.gvarin_map[key] = v
                finally:
                    pass
        #print "gvar", self.gvarin_map

    #
    #   'brief'	
    #   'param'	
    #   'return'
    #   'fcall' 
    #   'details'
    #   'depth'	
    # 获取函数头部
    def get_fun_header(self, name, elist):
        fun_str_map = {
            'proto'	: '', 
            'brief'	: '', 
            'param'	: '', 
            'return': '', 
            'fcall' : '',
            'gvarin' : '',
            'gvarout': '',
            'details': '',
        }
        fun_str = ''

        # 更新函数调用和输出全局
        self.update_fun_data(fun_str_map, 'fcall', self.fcall_map)
        self.update_fun_data(fun_str_map, 'gvarout', self.gvarout_map, VTYPE_GLOBAL)

        #print self.expr, "-----------"
        self.gvarin_map = self.analyze_gvin_data(self.expr)
        self.update_gvarin(self.gvarout_map, self.fcall_map)
        self.update_fun_data(fun_str_map, 'gvarin', self.gvarin_map, VTYPE_GLOBAL)

        pmap = self.get_param_map(self.gvarout_map, VTYPE_PARAM)

        # 遍历elist，此处elist为注释中的关键字
        for elem in elist:
            str1, str2 = get_split_str(elem[1])
            if (elem[0] == 'brief'):
                # brief有多行，需要合并
                if (name == str1):
                    fun_str_map['brief'] += str2
                else:
                    fun_str_map['brief'] += elem[1]
            #elif (elem[0] == 'param') or (elem[0][0:4] == 'gvar'):
            elif (elem[0] == 'param') :
                if str1 != '':
                    pmap[str1.lstrip()] = get_format_str(str2)
                # 对于参数来说，需要加分隔符：，并合并
                #print "===PARAM ", str1
                #fun_str_map[elem[0]] += str1
                #fun_str_map[elem[0]] += ': '
                #fun_str_map[elem[0]] += get_format_str(str2)
                #fun_str_map[elem[0]] += '\n'
            elif (elem[0] == 'return'):
                fun_str_map[elem[0]] += get_format_str(elem[1])
            else:
                try:
                    fun_str_map[elem[0]] += elem[1]
                except :
                    fun_str_map[elem[0]] = elem[1]
                    #print elem[0], elem[1]
                    pass

        #如果由于未写注释导致参数未正确识别
        for k,v in pmap.items():
            fun_str_map['param'] += k
            fun_str_map['param'] += ' : '
            fun_str_map['param'] += get_format_str(v)
            fun_str_map['param'] += '\n'
        #print pmap

        fun_str_map['proto'] = self.declaration_get()

        if (fun_str_map['brief'] == ''):
            # 如果brief描述为空，自动添加一个合适的brief
            fun_str_map['brief'] = comment_null_table['brief']%name

        for key in fun_str_map.iterkeys():
            # 如果是空的，则进行默认填充
            if (fun_str_map[key] == ''):
                fun_str_map[key] = comment_null_table[key]
        
        #for key, value in fun_str_map.items():
        #    print comment_translate_table[key]
        #    print value
        return fun_str_map

    def con_printer(self, name, header, exp, depth):
        import ccondraw
        ccondraw.print_fun_header(name, header)
        print(FUN_SEP)
        print 'FUNCTION:', name
        print FUN_LFMT%exp[TK_START], '{'
        ret = ccondraw.print_func_exp(exp, 1, 0)
        print FUN_LFMT%exp[TK_END], '}'
        print '*********************************@depth:', depth

    def basic_printer(self, name, header, exp, depth):
        if self.flag_get('verbose') :
            self.con_printer(name, header, exp, depth)

    def extend_printer(self, name, header, exp, depth):
        if self.flag_get('nodraw') ==0:
            print '----------adding page:', name, '@depth:', depth
        pass

    def printer(self, name, exp):
        match = self.flag_get('filter')
        if match != '':
            if name.find(match) >=0:
                print '_____Filter ', match, 'OK for', name
            else:
                return

        # 确保表达式有效（首、尾行号正常）
        if (exp[TK_START] < exp[TK_END]
                ):
            depth = DEFAULT_DEPTH

            # 解析注释
            comment = self.get_comment(exp[TK_START])
            comment += '\n'

            if self.flag_get('force-depth') != 0:
                # 如果设置了强制深度，照此执行
                depth = self.flag_get('force-depth')
            else:
                depth2 = self.get_comment_depth(exp[TK_START])
                depth = self.flag_get('depth')
                # 如果注释中获取的深度<
                if (depth2 != DEFAULT_DEPTH):
                    depth = depth2

            # 此处lexer需要指定，否则在根目录中调用有问题
            res = self.doxyp.parse(comment, lexer=self.lexer)

            #print "doxy list", self.elist
            header = self.get_fun_header(name, self.elist)

            self.basic_printer(name, header, exp, depth)
            #print self.elist
            self.extend_printer(name, header, exp, depth)

            self.reset()
            del self.elist[:]

# 定义全局变量
# gfun=cgrammar()
